home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d15 / hex.arc / HEX.C next >
Text File  |  1991-02-26  |  31KB  |  980 lines

  1. /*----------------------------------------------------------
  2.     HEX.C -- File Hex Dump Program
  3.       (c) Kamyar Goodarzi & Jim Boyce, 1990
  4.   ----------------------------------------------------------*/
  5.  
  6.  
  7.  
  8.  
  9. #include <windows.h>
  10. #include <string.h>
  11. #include <math.h>
  12. #include <sys\types.h>
  13. #include <sys\stat.h>
  14. #include "hex.h"
  15.  
  16.  
  17. // the following function prints the last file line if it is less than
  18. // 16 bytes.  I took the easy way out and used the sprintf to create
  19. // the last file line string.
  20.  
  21. void GetLastString (LONG lFileOffsetTmp, unsigned char *pBuffer) {
  22.  
  23.    int    i, j, c ;
  24.  
  25.    c = (count % 16) ;
  26.  
  27.    sprintf (printStr, "%.8lX  ", lFileOffsetTmp) ;
  28.    for (i = 0, j = 10 + 3 * c; i <= 16 - c; i++, j +=3)
  29.       sprintf ((printStr + j), "   ") ;
  30.    for (i = 0, j = 10; i < c; i++, j += 3, pBuffer++) {
  31.       sprintf ((printStr + j), " %.2X", *pBuffer) ;
  32.       sprintf ((printStr + 61 + i), "%c", *pBuffer) ;
  33.    }
  34.    *(printStr + j) = ' ' ;
  35.    strLength = 61 + c ;
  36. }
  37.  
  38.  
  39.  
  40.  
  41. // Reads characters from the user-selected file and fills a file buffer.
  42.  
  43. void FillBuff (HWND hwnd) {
  44.  
  45.    // Sets cursor to hourglass.
  46.    hSaveCursor = SetCursor (hHourGlass) ;
  47.  
  48.    // Reopens the file and in the case of errors, displays an appropriate
  49.    // message (if there is a file-open error, Hex Dump terminates).
  50.    if ((hFile = OpenFile ((LPSTR) NULL, &OFStruct, OF_REOPEN | OF_READ)) < 0) {
  51.       sprintf (str, "Error %d opening %s.", OFStruct.nErrCode, OpenName) ;
  52.       MessageBox (hwnd, (LPSTR) str, NULL, MB_OK | MB_ICONHAND) ;
  53.       SendMessage (hwnd, WM_DESTROY, 0, 0L) ;
  54.       return ;
  55.    }
  56.  
  57.    // Calculates the actual file offset.
  58.    lFileOffset = lFileLine * 16 ;
  59.  
  60.    // Positions the file pointer to the previously calculated file offset.
  61.    if ((lFileOffset = _llseek (hFile, lFileOffset, 0)) == -1) {
  62.       sprintf (str, "Error reading %s.", FileName) ;
  63.       MessageBox (hwnd, (LPSTR) str, NULL, MB_OK | MB_ICONHAND) ;
  64.       SendMessage (hwnd, WM_DESTROY, 0, 0L) ;
  65.       return ;
  66.    }
  67.  
  68.  
  69.    // Fills the buffer by reading from the file.
  70.    if ((count = _lread (hFile, (LPSTR) pFileBuf, FOURKBYTE)) == -1) {
  71.       sprintf (str, "Error reading %s.", FileName) ;
  72.       MessageBox (hwnd, (LPSTR) str, NULL, MB_OK | MB_ICONHAND) ;
  73.       SendMessage (hwnd, WM_DESTROY, 0, 0L) ;
  74.       return ;
  75.    }
  76.  
  77.  
  78.    // If the amount read is less than the size of the buffer, end of
  79.    // file is set TRUE.  Otherwise, end of file is FALSE.
  80.    if (count < FOURKBYTE)
  81.       endOfFile = TRUE ;
  82.    else
  83.       endOfFile = FALSE ;
  84.  
  85.  
  86.    // Calculate the number of lines inside the buffer.
  87.    nBufLines = (int) ceil ((double) count / 16.0) ;
  88.  
  89.  
  90.    // Close the file.
  91.    _lclose (hFile) ;
  92.  
  93.  
  94. }
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103. /*-------------------------------------------------------------------
  104.    Hex Main Windows procedure
  105.   -------------------------------------------------------------------*/
  106.  
  107.  
  108.  
  109. int PASCAL WinMain (HANDLE hInstance,
  110.                HANDLE hPrevInstance,
  111.                LPSTR lpszCmdLine,
  112.                int nCmdShow) {
  113.  
  114.    HWND         hwnd ;
  115.    MSG          msg ;
  116.    WNDCLASS     wndClass ;
  117.  
  118.    if (!hPrevInstance) {
  119.       wndClass.style            = CS_HREDRAW | CS_VREDRAW ;
  120.       wndClass.lpfnWndProc      = WndProc ;
  121.       wndClass.cbClsExtra       = 0 ;
  122.       wndClass.cbWndExtra       = 0 ;
  123.       wndClass.hInstance        = hInstance ;
  124.       wndClass.hIcon            = LoadIcon (hInstance, "Hex") ;
  125.       wndClass.hCursor          = LoadCursor (hInstance, "Hex") ;
  126.       wndClass.hbrBackground    = GetStockObject (WHITE_BRUSH) ;
  127.       wndClass.lpszMenuName     = "Hex" ;
  128.       wndClass.lpszClassName    = "Hex" ;
  129.  
  130.       RegisterClass (&wndClass) ;
  131.    }
  132.  
  133.    hInst = hInstance ;
  134.  
  135.    hHexMenu = LoadMenu (hInstance, "Hex") ;
  136.    lpHexTitle = lstrcpy ((LPSTR) str, "Hex Dump") ;
  137.  
  138.    hwnd = CreateWindow (
  139.          "Hex",
  140.          lpHexTitle,
  141.          WS_OVERLAPPEDWINDOW |
  142.          WS_VSCROLL |
  143.          WS_HSCROLL,
  144.          CW_USEDEFAULT,
  145.          CW_USEDEFAULT,
  146.          CW_USEDEFAULT,
  147.          CW_USEDEFAULT,
  148.          NULL,
  149.          hHexMenu,
  150.          hInstance,
  151.          NULL) ;
  152.  
  153.  
  154.    if (!hwnd)
  155.       return (FALSE) ;
  156.  
  157.  
  158.    ShowWindow (hwnd, nCmdShow) ;
  159.    UpdateWindow (hwnd) ;
  160.  
  161.    while (GetMessage (&msg, NULL, 0, 0)) {
  162.       TranslateMessage (&msg) ;
  163.       DispatchMessage (&msg) ;
  164.    }
  165.  
  166.    return msg.wParam ;
  167. }
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176. long FAR PASCAL WndProc (HWND hwnd,
  177.                    unsigned message,
  178.                    WORD wParam,
  179.                    LONG lParam) {
  180.  
  181.  
  182.  
  183.    unsigned char    *p ;
  184.  
  185.    HDC              hdc ;
  186.    LONG             lFileOffsetTmp, lScrollPos ;
  187.    short            i, x, y, nPaintBeg, nPaintEnd, nScrollInc ;
  188.    DWORD            lParameter ;
  189.  
  190.    PAINTSTRUCT      ps ;
  191.    TEXTMETRIC       tm ;
  192.    FARPROC          lpOpenDlg ;
  193.    FARPROC          lpProcAbout ;
  194.  
  195.  
  196.    switch (message) {
  197.  
  198.       case WM_CREATE :
  199.  
  200.          // Get device context so object can be selected based
  201.          // on the device.
  202.  
  203.          hdc = GetDC (hwnd) ;
  204.  
  205.          // Get system fixed font for calculating character height
  206.          // and width.
  207.          SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
  208.          GetTextMetrics (hdc, &tm) ;
  209.          nCharWidth = tm.tmAveCharWidth ;
  210.          nCharHeight = tm.tmHeight + tm.tmExternalLeading ;
  211.  
  212.          // Release the device context.
  213.  
  214.          ReleaseDC (hwnd, hdc) ;
  215.  
  216.          return (FALSE);
  217.  
  218.       case WM_COMMAND :
  219.  
  220.          switch (wParam) {
  221.  
  222.             case IDM_ABOUT :
  223.  
  224.                // if user picks the About menu item.
  225.                // use the WinAboutProc window procedure instead of
  226.                // the WndProc.
  227.  
  228.                lpProcAbout = MakeProcInstance (WinAboutProc, hInst) ;
  229.  
  230.                // display the dialogue box.
  231.                DialogBox (hInst,
  232.                      "AboutBox",
  233.                      hwnd,
  234.                      lpProcAbout) ;
  235.  
  236.                // set the window procedure back to WndProc.
  237.  
  238.                FreeProcInstance (lpProcAbout) ;
  239.  
  240.                // skip the remaining cases.
  241.                break ;
  242.  
  243.             case IDM_EXIT :
  244.  
  245.                // free the memory that was allocated to the file
  246.                // buffer.
  247.                hFileBuf = LocalFree (hFileBuf) ;
  248.  
  249.                // if encounter any errors display a message and quit
  250.                // the application.
  251.                if (hFileBuf) {
  252.                   MessageBox (hwnd,
  253.                            "Memory error. Terminating the program.",
  254.                            NULL, MB_OK | MB_ICONHAND) ;
  255.                }
  256.  
  257.                SendMessage (hwnd, WM_DESTROY, 0, 0L) ;
  258.                break ;
  259.  
  260.             case IDM_HELP :
  261.  
  262.                // if user selects help menu item, use the WinHelp
  263.                // function to display contents of hex.hlp.
  264.  
  265.                WinHelp (hwnd, "HEX.HLP", HELP_INDEX, NULL) ;
  266.                break ;
  267.  
  268.             case IDM_CLOSE :
  269.  
  270.                // user selects the close menu item.
  271.                // set file handle to 0 (no file is currently open).
  272.                hFile = 0 ;
  273.  
  274.                // give up the allocated memory.  if any errors
  275.                // display a message and terminate the application.
  276.  
  277.                hFileBuf = LocalFree (hFileBuf) ;
  278.                if (hFileBuf) {
  279.                   MessageBox (hwnd,
  280.                            "Memory error. Terminating the program.",
  281.                            NULL, MB_OK | MB_ICONHAND) ;
  282.                   SendMessage (hwnd, WM_DESTROY, 0, 0L) ;
  283.                }
  284.  
  285.                // gray (disable) the close menu item.
  286.                EnableMenuItem (hHexMenu, IDM_CLOSE, MF_GRAYED) ;
  287.  
  288.                // strip the file name from the title and display
  289.                // it in the title bar.
  290.  
  291.                lpHexTitle = lstrcpy ((LPSTR) str, "Hex Dump") ;
  292.                SetWindowText (hwnd, lpHexTitle) ;
  293.  
  294.                // clear the entir client area and repaint.
  295.                InvalidateRect (hwnd, NULL, TRUE) ;
  296.  
  297.                // Build the low and high words of the message
  298.                // parameter.
  299.                lParameter = ((DWORD) nClientHeight << 16) |
  300.                            nClientWidth ;
  301.  
  302.                // send the above calculated parameter as part of the
  303.                // WM_SIZE message.
  304.                SendMessage (hwnd, WM_SIZE, SIZENORMAL, lParameter) ;
  305.  
  306.                break ;
  307.  
  308.             case IDM_OPEN :
  309.  
  310.                // if the file buffer handle is 0 (no previously
  311.                // allocated memory), allocated memory for the
  312.                // file buffer.  if an error was encountered, display
  313.                // an error message return.
  314.  
  315.                if (!hFileBuf)
  316.                   if ((hFileBuf = LocalAlloc (LMEM_MOVEABLE, FOURKBYTE+16)) == NULL) {
  317.                      MessageBox (hwnd, "Not Enough Memory.", NULL, MB_OK | MB_ICONHAND) ;
  318.                      return FALSE ;
  319.                   }
  320.                // setup the OpenDlg window procedure to service
  321.                // the needs of the dialogue box.
  322.                lpOpenDlg = MakeProcInstance (
  323.                      (FARPROC) OpenDlg, hInst) ;
  324.  
  325.                DialogBox (hInst, "Open", hwnd, lpOpenDlg) ;
  326.                // let WndProc window procedure handle windows messages.
  327.                FreeProcInstance (lpOpenDlg) ;
  328.  
  329.                // if a file was not opened, return from this procedure.
  330.                if (!hFile)
  331.                   return FALSE ;
  332.  
  333.                // enable the Close menu item.
  334.                EnableMenuItem (hHexMenu, IDM_CLOSE, MF_ENABLED) ;
  335.  
  336.                // obtain the file stauts (size ...). File attributes
  337.                // will be written in the FileStatus structure.
  338.                fstat (hFile, &FileStatus) ;
  339.  
  340.                // calculate the total number of linse in that file.
  341.                lTotalFileLines = (LONG) ceil ((double)
  342.                                FileStatus.st_size / 16.0) ;
  343.  
  344.                // display the file size and name in the title bar.
  345.                sprintf (printStr, " [%.8lX] hex Bytes", FileStatus.st_size) ;
  346.                lpHexTitle = lstrcat (lstrcat (lstrcpy ((LPSTR) str, "Hex Dump -- "),
  347.                         (LPSTR) OpenName),   (LPSTR) printStr) ;
  348.                SetWindowText (hwnd, lpHexTitle) ;
  349.  
  350.                // calculate the number of file lines per scroll bar
  351.                // increment.
  352.                if (lTotalFileLines > MAXINT)
  353.                   nNumOfLines = MAXINT ;
  354.                else
  355.                   nNumOfLines = (int) ceil ((double) FileStatus.st_size
  356.                                        / 16.0) ;
  357.                // set the file offset and the file line offset to start (0).
  358.                // set the cursor to the hourglass, use LocalLock to obtain
  359.                // a pointer to the file buffer.
  360.                // read 4K bytes into the buffer.  close the file
  361.                // set cursor back to mouse.
  362.  
  363.  
  364.                lFileOffset = 0L ;
  365.                lFileLine = 0L ;
  366.                hSaveCursor = SetCursor (hHourGlass) ;
  367.                pFileBuf = LocalLock (hFileBuf) ;
  368.                nWinFirstLine = 0 ;
  369.                count = _lread (hFile, (LPSTR) pFileBuf, FOURKBYTE) ;
  370.                _lclose (hFile) ;
  371.                SetCursor (hSaveCursor) ;
  372.  
  373.                // if the _lread function return value is equal to -1 (error),
  374.                // display an error message and return.
  375.  
  376.                if (count == -1) {
  377.                   sprintf (str, "Error reading %s.", FileName) ;
  378.                   MessageBox (hwnd, (LPSTR) str, NULL,
  379.                         MB_OK | MB_ICONHAND) ;
  380.                   return (FALSE) ;
  381.                }
  382.  
  383.                // if count is less than the buffer size, set end of file
  384.                // flag to TRUE; otherwise set to FALSE.
  385.                if (count < FOURKBYTE)
  386.                   endOfFile = TRUE ;
  387.                else
  388.                   endOfFile = FALSE ;
  389.  
  390.                // calculate number of the file lines present in the
  391.                // buffer, and release the buffer pointer.
  392.                nBufLines = ceil ((double) count / 16.0) ;
  393.                LocalUnlock (hFileBuf) ;
  394.  
  395.  
  396.  
  397.                // Clear the client area for repaint.
  398.                InvalidateRect (hwnd, NULL, TRUE) ;
  399.  
  400.                // reset the scroll bar position to 0.
  401.                nVSBarPos = 0 ;
  402.  
  403.                // Build the low and high words of the message
  404.                // parameter.
  405.                lParameter = ((DWORD) nClientHeight << 16) |
  406.                            nClientWidth ;
  407.  
  408.                // send the above calculated parameter as part of the
  409.                // WM_SIZE message.
  410.                SendMessage (hwnd, WM_SIZE, SIZENORMAL, lParameter) ;
  411.  
  412.          }
  413.          return FALSE ;
  414.  
  415.       case WM_SIZE :
  416.  
  417.          // calculate the client area's width and height and the number
  418.          // of lines that can fit in that area.
  419.          nClientWidth = LOWORD (lParam) ;
  420.          nClientHeight = HIWORD (lParam) ;
  421.          nWinLines = nClientHeight / nCharHeight ;
  422.  
  423.  
  424.          // this section adds/removes scroll bars depending on the
  425.          // size of client area and adjusts the scroll bar position.
  426.          // this is only done if a file is open.  when files are closed
  427.          if(hFile) {
  428.             if (nWinLines >= nNumOfLines)
  429.                nVSBarMax = 0 ;
  430.             else
  431.                nVSBarMax = nNumOfLines + 4 -nWinLines ;
  432.  
  433.             nVSBarPos = min (nVSBarPos, nVSBarMax) ;
  434.             nHSBarMax = max (0,2 + (79 * nCharWidth - nClientWidth) / nCharWidth) ;
  435.             nHSBarPos = min (nHSBarPos, nHSBarMax) ;
  436.          }
  437.          else {
  438.             nVSBarMax = nVSBarPos = nHSBarMax = nHSBarPos = 0 ;
  439.          }
  440.  
  441.          // set the vertical scroll bar's max value and position.
  442.          SetScrollRange (hwnd, SB_VERT, 0, nVSBarMax, FALSE) ;
  443.          SetScrollPos (hwnd, SB_VERT, nVSBarPos, TRUE) ;
  444.  
  445.          // set the horizontal scroll bar's max value and position.
  446.          SetScrollRange (hwnd, SB_HORZ, 0, nHSBarMax, FALSE) ;
  447.          SetScrollPos   (hwnd, SB_HORZ, nHSBarPos, TRUE) ;
  448.  
  449.          return FALSE ;
  450.  
  451.       // Service all vertical scroll messages.
  452.       case WM_VSCROLL :
  453.  
  454.          // calculate the temporary scroll/file position.
  455.          lScrollPos = lFileLine + nWinFirstLine ;
  456.  
  457.          switch (wParam) {
  458.  
  459.             case SB_TOP :
  460.                lScrollPos = 0L ;
  461.                break ;
  462.  
  463.             case SB_BOTTOM :
  464.                lScrollPos = lTotalFileLines - nWinLines ;
  465.                break ;
  466.  
  467.             case SB_LINEUP :
  468.  
  469.                if (lScrollPos != 0) {
  470.                   lScrollPos -=  1 ;
  471.                }
  472.                break ;
  473.  
  474.  
  475.             case SB_LINEDOWN :
  476.  
  477.                if (lScrollPos < lTotalFileLines - nWinLines) {
  478.                   lScrollPos = lFileLine + nWinFirstLine + 1 ;
  479.                }
  480.                break ;
  481.  
  482.  
  483.             case SB_PAGEUP :
  484.  
  485.                if (lScrollPos > 0) {
  486.                   lScrollPos = lFileLine + nWinFirstLine + min (-1, -nWinLines) ;
  487.                   if (lScrollPos < 0)
  488.                      lScrollPos = 0 ;
  489.                }
  490.                break ;
  491.  
  492.  
  493.             case SB_PAGEDOWN :
  494.  
  495.                if (lScrollPos   >= lTotalFileLines - 2 * nWinLines)
  496.                   lScrollPos = lTotalFileLines - nWinLines ;
  497.                else
  498.                   lScrollPos = lFileLine + nWinFirstLine + max (1, nWinLines) ;
  499.                break ;
  500.  
  501.  
  502.             case SB_THUMBPOSITION :
  503.  
  504.                // if the thumbposition has changed do the following.
  505.                if (LOWORD (lParam) != nVSBarPos) {
  506.  
  507.                   // if set to the end of the file and less than
  508.                   // one page displayed, set the temp. file pointer
  509.                   // to then end of file minus a screen full.
  510.                   if (LOWORD (lParam) >= nNumOfLines - nWinLines)
  511.                      lScrollPos = lTotalFileLines - nWinLines ;
  512.                   else
  513.  
  514.                      // else calculate the new file position.
  515.                      lScrollPos = (LONG) ceil (((double)LOWORD (lParam)) *
  516.                             ((double) lTotalFileLines / (double) nNumOfLines)) ;
  517.                }
  518.          }
  519.  
  520.          // if lScrollPos is changed do the following:
  521.          if (lScrollPos != lFileLine + nWinFirstLine) {
  522.  
  523.             // obtain a pointer to the local buffer memory.
  524.             pFileBuf = LocalLock (hFileBuf) ;
  525.  
  526.             // if the scroll amount is than a client area full, scroll
  527.             // the window, otherwise clear it and repaint.
  528.             if ((labs (lScrollPos - (lFileLine
  529.                      + nWinFirstLine))) < (LONG) nWinLines)
  530.                ScrollWindow (hwnd, 0, -nCharHeight *
  531.                      (int) (lScrollPos -
  532.                      (lFileLine + nWinFirstLine))
  533.                      , NULL, NULL) ;
  534.             else
  535.                InvalidateRect (hwnd, NULL, TRUE) ;
  536.  
  537.             // calculate the new vertical scroll position.
  538.             nVSBarPos = (int) ceil (((double) lScrollPos /
  539.                               (double) lTotalFileLines) * nNumOfLines) ;
  540.  
  541.             // report the new vertical position to windows.
  542.             SetScrollPos (hwnd, SB_VERT, nVSBarPos, TRUE) ;
  543.  
  544.             // if the new file pointer is less than the current, read
  545.             // a buffer full and set the windows first line offset to
  546.             // 0.
  547.             if (lScrollPos < lFileLine) {
  548.                lFileLine = lScrollPos ;
  549.                nWinFirstLine = 0 ;
  550.                FillBuff (hwnd) ;
  551.             }
  552.             else {
  553.  
  554.                // if the new file pointer is greater than the current
  555.                // and does not land in the file buffer area do the
  556.                // following.
  557.                if(lScrollPos > lFileLine + nBufLines + 1 - nWinLines) {
  558.  
  559.                   // if it is not the end of file adjust the current
  560.                   // file pointer and fill the buffer with data.
  561.                   if (!endOfFile) {
  562.                      lFileLine = lScrollPos ;
  563.                      nWinFirstLine = 0 ;
  564.                      FillBuff (hwnd) ;
  565.                   }
  566.                   else
  567.  
  568.                      // else adjust the offset of the first line
  569.                      // in the client area.
  570.                      nWinFirstLine = (int) (nBufLines - nWinLines) ;
  571.                }
  572.                else
  573.  
  574.                   // if the new file pointer lands in the buffer
  575.                   // then adjust offset of the first line in the
  576.                   // client area.
  577.                   nWinFirstLine = (int) (lScrollPos - lFileLine) ;
  578.             }
  579.  
  580.             // update the client area and release the buffer memory
  581.             // pointer.
  582.             UpdateWindow (hwnd) ;
  583.             LocalUnlock (hFileBuf) ;
  584.          }
  585.  
  586.          return FALSE ;
  587.  
  588.       case WM_HSCROLL :
  589.  
  590.          switch (wParam) {
  591.  
  592.             case SB_LINEUP :
  593.                nScrollInc = -1 ;
  594.                break ;
  595.  
  596.             case SB_LINEDOWN :
  597.                nScrollInc = 1 ;
  598.                break ;
  599.  
  600.             case SB_PAGEUP :
  601.                nScrollInc = -5 ;
  602.                break ;
  603.  
  604.             case SB_PAGEDOWN :
  605.                nScrollInc = 5 ;
  606.                break ;
  607.  
  608.             case SB_THUMBTRACK :
  609.                nScrollInc = LOWORD (lParam) - nHSBarPos ;
  610.                break ;
  611.  
  612.             default :
  613.                nScrollInc = 0 ;
  614.          }
  615.  
  616.          // use the user horizontal scroll request to calculate
  617.          // the new horizontal scroll position and the contents of the
  618.          // client area.
  619.  
  620.          if (nScrollInc = max (-nHSBarPos,
  621.             min (nScrollInc, nHSBarMax - nHSBarPos))) {
  622.             nHSBarPos += nScrollInc ;
  623.             ScrollWindow (hwnd, -nCharWidth * nScrollInc, 0, NULL, NULL) ;
  624.             SetScrollPos (hwnd, SB_HORZ, nHSBarPos, TRUE) ;
  625.          }
  626.          return FALSE ;
  627.  
  628.       case WM_KEYDOWN :
  629.  
  630.          switch (wParam) {
  631.  
  632.             case VK_HOME :
  633.                SendMessage (hwnd, WM_VSCROLL, SB_TOP, 0L) ;
  634.                break ;
  635.  
  636.             case VK_END :
  637.                SendMessage (hwnd, WM_VSCROLL, SB_BOTTOM, 0L) ;
  638.                break ;
  639.  
  640.             case VK_PRIOR :
  641.                SendMessage (hwnd, WM_VSCROLL, SB_PAGEUP, 0L) ;
  642.                break ;
  643.  
  644.             case VK_NEXT :
  645.                SendMessage (hwnd, WM_VSCROLL, SB_PAGEDOWN, 0L) ;
  646.                break ;
  647.  
  648.             case VK_UP :
  649.                SendMessage (hwnd, WM_VSCROLL, SB_LINEUP, 0L) ;
  650.                break ;
  651.  
  652.             case VK_DOWN :
  653.                SendMessage (hwnd, WM_VSCROLL, SB_LINEDOWN, 0L) ;
  654.                break ;
  655.  
  656.             case VK_LEFT :
  657.                SendMessage (hwnd, WM_HSCROLL, SB_PAGEUP, 0L) ;
  658.                break ;
  659.  
  660.             case VK_RIGHT :
  661.                SendMessage (hwnd, WM_HSCROLL, SB_PAGEDOWN, 0L) ;
  662.                break ;
  663.          }
  664.          return FALSE ;
  665.  
  666.       case WM_PAINT :
  667.  
  668.          // obtain a device context handle and the attributes of the
  669.          // paint area using the BeginPaint function.
  670.  
  671.          hdc = BeginPaint (hwnd, &ps) ;
  672.  
  673.          // do the following  block only if a file is open, since the
  674.          // client area will be blank otherwise.
  675.  
  676.          if (hFile) {
  677.  
  678.             // obtain a pointer to the allocated memory block using
  679.             // the LocalLock function.
  680.  
  681.             pFileBuf = LocalLock (hFileBuf) ;
  682.  
  683.             // use the system fixed font.
  684.  
  685.             SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT)) ;
  686.  
  687.             // calculate the begin and end of the invalid client area.
  688.             // the invalid client area is the area that must be
  689.             // repainted.
  690.  
  691.             nPaintBeg = max (0, ps.rcPaint.top / nCharHeight -1) ;
  692.             nPaintEnd = ps.rcPaint.bottom / nCharHeight ;
  693.  
  694.             // calculate the leftmost character based on the
  695.             // horizontal scroll bar position.
  696.  
  697.             x = nCharWidth * (1 - nHSBarPos) ;
  698.  
  699.             // obtain a pointer to the next line to be displayed
  700.             // within the new paint area.
  701.  
  702.             p = nWinFirstLine * 16 + pFileBuf + (nPaintBeg * 16) ;
  703.  
  704.             // calculate the file position (byte value) for each line.
  705.  
  706.             lFileOffsetTmp = ((lFileLine + nWinFirstLine) * 16)
  707.                         + (nPaintBeg * 16) ;
  708.  
  709.             // while in paint area, and not outside the buffer:
  710.             // from top of paint area to end of paint area, paint
  711.             // the file offset, byte value, and ASCII string.
  712.  
  713.             for (i = nPaintBeg; i <= nPaintEnd   && p < pFileBuf + count;
  714.                      i++, p += 16, lFileOffsetTmp += 16) {
  715.  
  716.                // calculate vertical position of the first line
  717.                // of the paint area.
  718.  
  719.                y = nCharHeight * i ;
  720.  
  721.                // if end of file and the last line is less than
  722.                // 16 bytes use the GetLastString to obtain the
  723.                // last file line.
  724.                if (endOfFile && (pFileBuf + count - p < 16) &&
  725.                         count % 16)
  726.                   GetLastString (lFileOffsetTmp, p) ;
  727.                else
  728.  
  729.                   // otherwise use sprintf to print 16 byte to a
  730.                   // string.
  731.  
  732.                   strLength = sprintf (printStr, formatString,
  733.                      lFileOffsetTmp, *(p+0), *(p+1), *(p+2), *(p+3), *(p+4),
  734.                      *(p+5), *(p+6), *(p+7), *(p+8), *(p+9), *(p+10),
  735.                      *(p+11), *(p+12), *(p+13), *(p+14), *(p+15),
  736.                      *(p+0), *(p+1), *(p+2), *(p+3), *(p+4),
  737.                      *(p+5), *(p+6), *(p+7), *(p+8), *(p+9), *(p+10),
  738.                      *(p+11), *(p+12), *(p+13), *(p+14), *(p+15)) ;
  739.  
  740.                // display the string in the client area.
  741.                TextOut (hdc, x, y, (LPSTR) printStr, strLength) ;
  742.             }
  743.  
  744.          // release the file buffer pointer.
  745.          LocalUnlock (hFileBuf) ;
  746.          }
  747.  
  748.          // end paint.
  749.          EndPaint (hwnd, &ps) ;
  750.          return FALSE ;
  751.  
  752.       case WM_DESTROY :
  753.  
  754.          // to end application execution, free the allocated memory
  755.          // and post a quit message.
  756.          LocalFree (hFileBuf) ;
  757.          PostQuitMessage (0) ;
  758.          return FALSE ;
  759.    }
  760.  
  761.    // All messages not processed by this procedure, including system
  762.    // messages, are passed to DefWindowProc.
  763.    return (DefWindowProc (hwnd, message, wParam, lParam)) ;
  764. }
  765.  
  766.  
  767.  
  768.  
  769. /*-----------------------------------------------------------------------
  770.  
  771.   The Window Procedure for About dialog box.  Dialog functions must
  772.   service user inputs only.
  773.  
  774.  
  775.   -----------------------------------------------------------------------*/
  776.  
  777.  
  778.  
  779.  
  780.  
  781. BOOL FAR PASCAL WinAboutProc (HWND hDlg,
  782.                   unsigned message,
  783.                   WORD wParam,
  784.                   LONG lParam)
  785.  
  786.  
  787. {
  788.    switch (message) {
  789.  
  790.       case WM_INITDIALOG :          // return TRUE to initialize
  791.                                     // the box.  This will pass
  792.          return (TRUE) ;                // the focus to the
  793.                                     // default push button.
  794.       case WM_COMMAND :
  795.  
  796.          switch (wParam) {
  797.  
  798.             case IDOK :                // if user input is OK or
  799.             case IDCANCEL :            // cancel, end the dialog.
  800.                EndDialog (hDlg, TRUE) ;
  801.                return TRUE ;
  802.          }
  803.    }
  804.  
  805.    return (FALSE) ;
  806.  
  807. }
  808.  
  809.  
  810. /*-----------------------------------------------------------------------
  811.  
  812.   The remaining of this program has been taken from examples in the
  813.   Microsoft (R) Windows Guide to Programming book.   This section of the
  814.   code opens the file dialogue box, assists the controls in the dialogue
  815.   box to display directories, filenames, etc.  It also opens the file
  816.   selected by the user.
  817.  
  818.   -----------------------------------------------------------------------*/
  819.  
  820.  
  821.  
  822.  
  823. void UpdateListBox (HWND hDlg) {
  824.  
  825.    strcpy (str, DefPath) ;
  826.    strcat (str, DefSpec) ;
  827.    DlgDirList (hDlg, str, IDC_LISTBOX, IDC_PATH, 0x4010) ;
  828.    SetDlgItemText (hDlg, IDC_EDIT, DefSpec) ;
  829. }
  830.  
  831.  
  832.  
  833.  
  834. void SeparateFile (HWND hDlg,
  835.                LPSTR lpDestPath,
  836.                LPSTR lpDestFileName,
  837.                LPSTR lpSrcFileName) {
  838.  
  839.    LPSTR lpTmp ;
  840.    char cTmp ;
  841.  
  842.    lpTmp = lpSrcFileName + (long) lstrlen (lpSrcFileName) ;
  843.  
  844.    while (*lpTmp != ':' && *lpTmp != '\\' && lpTmp > lpSrcFileName)
  845.       lpTmp = AnsiPrev (lpSrcFileName, lpTmp) ;
  846.  
  847.    if (*lpTmp != ':' && *lpTmp != '\\') {
  848.       lstrcpy (lpDestFileName, lpSrcFileName) ;
  849.       lpDestPath[0] = 0 ;
  850.       return ;
  851.    }
  852.  
  853.    lstrcpy (lpDestFileName, lpTmp + 1) ;
  854.    cTmp = *(lpTmp + 1) ;
  855.    lstrcpy (lpDestPath, lpSrcFileName) ;
  856.    *(lpTmp + 1) = cTmp ;
  857.    lpDestPath [(lpTmp - lpSrcFileName) + 1] = 0 ;
  858. }
  859.  
  860.  
  861.  
  862.  
  863. void ChangeDefExt (PSTR Ext, PSTR Name) {
  864.  
  865.    PSTR pTptr ;
  866.  
  867.    pTptr = Name ;
  868.  
  869.    while (*pTptr && * pTptr != '.')
  870.       pTptr++ ;
  871.  
  872.    if (*pTptr)
  873.       if (!strchr (pTptr, '*') && !strchr (pTptr, '?'))
  874.          strcpy (Ext, pTptr) ;
  875. }
  876.  
  877.  
  878.  
  879.  
  880.  
  881. void AddExt (PSTR Name, PSTR Ext) {
  882.  
  883.    PSTR pTptr ;
  884.  
  885.    pTptr = Name ;
  886.  
  887.    while (*pTptr && *pTptr != '.')
  888.       pTptr++ ;
  889.  
  890.    if (*pTptr != '.')
  891.       strcat (Name, Ext) ;
  892. }
  893.  
  894.  
  895.  
  896.  
  897.  
  898.  
  899.  
  900. HANDLE FAR PASCAL OpenDlg (HWND hDlg,
  901.                      unsigned message,
  902.                      WORD wParam,
  903.                      LONG lParam) {
  904.  
  905.    WORD index ;
  906.    PSTR pTptr ;
  907.  
  908.    switch (message) {
  909.       case WM_COMMAND :
  910.          switch (wParam) {
  911.             case IDC_LISTBOX :
  912.                switch (HIWORD (lParam)) {
  913.                   case LBN_SELCHANGE :
  914.                      if (!DlgDirSelect (hDlg, str, IDC_LISTBOX)) {
  915.                         SetDlgItemText (hDlg, IDC_EDIT, str) ;
  916.                         SendDlgItemMessage (hDlg, IDC_EDIT,
  917.                               EM_SETSEL,
  918.                               NULL,
  919.                               MAKELONG (0, 0x7fff)) ;
  920.                      }
  921.                      else {
  922.                         strcat (str, DefSpec) ;
  923.                         DlgDirList (hDlg, str, IDC_LISTBOX,
  924.                               IDC_PATH, 0x4010) ;
  925.                      }
  926.                      break ;
  927.                   case LBN_DBLCLK :
  928.                      goto openFile ;
  929.                }
  930.                return (TRUE) ;
  931.             case IDOK :
  932. openFile:
  933.                GetDlgItemText (hDlg, IDC_EDIT, OpenName, 128) ;
  934.                if (strchr (OpenName, '*') || strchr (OpenName, '?')) {
  935.                   SeparateFile (hDlg, (LPSTR) str,
  936.                         (LPSTR) DefSpec,
  937.                         (LPSTR) OpenName) ;
  938.                   if (str[0])
  939.                      strcpy (DefPath, str) ;
  940.                   ChangeDefExt (DefExt, DefSpec) ;
  941.                   UpdateListBox (hDlg) ;
  942.                   return (TRUE) ;
  943.                }
  944.                if (!OpenName[0]) {
  945.                   MessageBox (hDlg, "No filename specified.",
  946.                         NULL, MB_OK | MB_ICONQUESTION) ;
  947.                   return (TRUE) ;
  948.                }
  949.                if ((hFile = OpenFile (OpenName, (LPOFSTRUCT) &OFStruct,
  950.                      OF_READ)) < 0) {
  951.  
  952.                   sprintf (str, "Error %d opening %s.",
  953.                         OFStruct.nErrCode, OpenName) ;
  954.                   MessageBox (hDlg, (LPSTR) str, NULL, MB_OK | MB_ICONHAND) ;
  955.                }
  956.                else {
  957.                   strcpy (FileName, OpenName) ;
  958.                   EndDialog (hDlg, hFile) ;
  959.                   return (FALSE) ;
  960.                }
  961.             case IDCANCEL :
  962.                EndDialog (hDlg, NULL) ;
  963.                hFile = 0 ;
  964.                return (FALSE) ;
  965.          }
  966.          break ;
  967.       case WM_INITDIALOG :
  968.          UpdateListBox (hDlg) ;
  969.          SetDlgItemText (hDlg, IDC_EDIT, DefSpec) ;
  970.          SendDlgItemMessage (hDlg,
  971.                IDC_EDIT,
  972.                EM_SETSEL,
  973.                NULL,
  974.                MAKELONG (0, 0x7fff)) ;
  975.          SetFocus (GetDlgItem (hDlg, IDC_EDIT)) ;
  976.          return (FALSE) ;
  977.    }
  978.    return (FALSE) ;
  979. }
  980.